package com.ctbri.containerindepth;

import java.util.AbstractSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public class SimpleHashSet_Ex24<E> extends AbstractSet<E> {

	static final int SIZE = 997;
	
	@SuppressWarnings("unchecked")
	private LinkedList<E>[] buckets = new LinkedList[SIZE];
	
	@Override
	public boolean add(E e) {
		int index = Math.abs(e.hashCode()) % SIZE;
		if(buckets[index] == null) {
			buckets[index] = new LinkedList<>();
		}
		LinkedList<E> list = new LinkedList<>();
		ListIterator<E> it = list.listIterator();
		while(it.hasNext()) {
			E value = it.next();
			if(value.equals(e)){
				return false;
			}
		}
		list.add(e);
		return true;
	}
	@Override
	public Iterator<E> iterator() {
		return new Iterator<E>() {
			private int count;
			private boolean canRemove;
			private int index1, index2;
			
			@Override
			public boolean hasNext() {
				return count < size();
			}

			@Override
			public E next() {
				if(hasNext()) {
					canRemove = true;
					++count;
					for(;;) {
						while(buckets[index1] == null)
							index1++;
						try{
							return buckets[index1].get(index2++);
						} catch(IndexOutOfBoundsException e) {
							index1++;
							index2 = 0;
						}
					}
				}
				throw new NoSuchElementException();
			}
			
			@Override
			public void remove() {
				if(canRemove) {
					canRemove = false;
					buckets[index1].remove(--index2);
					if(buckets[index1].isEmpty())
						buckets[index1++] = null;
					--count;
				} else {
					throw new IllegalStateException();
				}
			}
		};
	}

	@Override
	public int size() {
		int size = 0;
		for(LinkedList<E> list : buckets){
			size += list.size();
		}
		return size;
	}

}
